#ifndef __CORE_BOUND_H__
#define __CORE_BOUND_H__
#include "CoreDefine.h"
#include "Vector3.h"

namespace Core
{
	class rtMatrix3;
	class rtPlane;
	class rtRotation;
	class rtSphere;

	class rtBounds
	{
	public:
		rtBounds(void);
		explicit rtBounds(const rtVector3& mins, const rtVector3& maxs);
		explicit rtBounds(const rtVector3& point);

		static rtBounds      bound_zero;

		const rtVector3& 	operator [] (const int index) const;
		rtVector3& 		    operator [] (const int index);
		rtBounds		        operator + (const rtVector3& t) const;
		rtBounds& 		    operator += (const rtVector3& t);
		rtBounds		        operator * (const rtMatrix3& r) const;
		rtBounds& 		    operator *= (const rtMatrix3& r);
		rtBounds		        operator + (const rtBounds& a) const;
		rtBounds& 		    operator += (const rtBounds& a);
		rtBounds		        operator - (const rtBounds& a) const;
		rtBounds& 		    operator -= (const rtBounds& a);

		bool			compare(const rtBounds& a) const;
		bool			compare(const rtBounds& a, const float epsilon) const;
		bool			operator == (const rtBounds& a) const;
		bool			operator != (const rtBounds& a) const;

		void			clear(void);
		void			zero(void);

		rtVector3		getCenter(void) const;
		float			getRadius(void) const;
		float			getRadius(const rtVector3& center) const;
		float			getVolume(void) const;
		bool			isCleared(void) const;

		bool			addPoint(const rtVector3& v);
		bool			addBounds(const rtBounds& a);
		rtBounds		    intersect(const rtBounds& a) const;
		rtBounds& 		intersectSelf(const rtBounds& a);
		rtBounds		    expand(const float d) const;
		rtBounds& 		expandSelf(const float d);
		rtBounds		    translate(const rtVector3& translation) const;
		rtBounds& 		translateSelf(const rtVector3& translation);
		rtBounds		    rotate(const rtMatrix3& rotation) const;
		rtBounds& 		rotateSelf(const rtMatrix3& rotation);

		float			planeDistance(const rtPlane& plane) const;
		int				planeSide(const rtPlane& plane, const float epsilon = ON_EPSILON) const;

		bool			containsPoint(const rtVector3& p) const;
		bool			intersectsBounds(const rtBounds& a) const;
		bool			lineIntersection(const rtVector3& start, const rtVector3& end) const;
		
		bool			rayIntersection(const rtVector3& start, const rtVector3& dir, float& scale) const;

		void			fromTransformedBounds(const rtBounds& bounds, const rtVector3& origin, const rtMatrix3& axis);
		
		void			fromPoints(const rtVector3 *points, const int numPoints);
		
		void			fromPointTranslation(const rtVector3& point, const rtVector3& translation);
		void			fromBoundsTranslation(const rtBounds& bounds, const rtVector3& origin, const rtMatrix3& axis, const rtVector3& translation);
		
		void			fromPointRotation(const rtVector3& point, const rtRotation& rotation);
		void			fromBoundsRotation(const rtBounds& bounds, const rtVector3& origin, const rtMatrix3& axis, const rtRotation& rotation);

		void			toPoints(rtVector3 points[8]) const;
		rtSphere		toSphere(void) const;

		void			axisProjection(const rtVector3& dir, float& min, float& max) const;
		void			axisProjection(const rtVector3& origin, const rtMatrix3& axis, const rtVector3& dir, float& min, float& max) const;

	private:
		rtVector3		m_Bound[2];
	};
}
#endif



